/*
 * Copyright (c) 2006-2021, Ulandlink Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-08-18     lfz         first version
 */

#include <rtthread.h>
#include "pin.h"
#include "drv_gpio.h"

#ifdef RT_USING_SERIAL
#include "drv_uart.h"
#include <serial.h>
#include <rthw.h>

typedef struct 
{
	const char 			   *name;	
	uint32_t 				usart_periph;
	IRQn_Type        		irq;
	rcu_periph_enum 		per_clk;        	   //Todo: 5bits
	rcu_periph_enum 		tx_gpio_clk;    	   //Todo: 5bits
	rcu_periph_enum 		rx_gpio_clk;   		   //Todo: 5bits 
    #ifdef RT_SERIAL_USING_DMA
    rcu_periph_enum 		dma_clk;        	   //Todo: 5bits
    uint32_t 				dma_periph;
    dma_channel_enum        dma_tx_channel;
    dma_channel_enum        dma_rx_channel;
    #endif
    uint32_t                dev_flag;
	uint32_t 				tx_port;               //Todo: 4bits
	uint16_t 				tx_af;                 //Todo: 4bits
	uint16_t 				tx_pin;                //Todo: 4bits
	uint32_t 				rx_port;               //Todo: 4bits
	uint16_t 				rx_af;                 //Todo: 4bits
	uint16_t 				rx_pin;                //Todo: 4bits
    uint16_t 				rts_pin;                //Todo: 4bits
	uint16_t 				cts_pin;                //Todo: 4bits
    
}uart_config_param;

typedef struct 
{
	uart_config_param 		*uart_config;
	struct rt_serial_device  serial;
}drv_uart_t;

enum
{
#ifdef BSP_USING_UART0
	uart0    = 0,
#endif

#ifdef BSP_USING_UART1
	uart1,
#endif

#ifdef BSP_USING_UART2
	uart2,
#endif
	
#ifdef BSP_USING_UART3
	uart3,
#endif
	
#ifdef BSP_USING_UART4
	uart4,
#endif
	
#ifdef BSP_USING_UART5
	uart5,
#endif

#ifdef BSP_USING_UART6
	uart6,
#endif

#ifdef BSP_USING_UART7
	uart7,
#endif
};

static uart_config_param uart_config_array[] =
{
#ifdef BSP_USING_UART0
{
	.name           = DEBUG_UART_NAME,
	.usart_periph   = USART0,                                 // uart peripheral index
	.irq            = USART0_IRQn,                            // uart iqrn
	.per_clk        = RCU_USART0, 
    .dma_clk        = RCU_DMA1,
    .dma_periph     = DMA1,
    .dma_tx_channel = DMA_CH7,
    .dma_rx_channel = DMA_CH2,
    .dev_flag       = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
    .tx_gpio_clk    = RCU_GPIOA, 
    .rx_gpio_clk    = RCU_GPIOA,                              // periph clock, tx gpio clock, rt gpio clock
	.tx_port        = GPIOA, 
    .tx_af          = GPIO_AF_7, 
    .tx_pin         = GPIO_PIN_9,                            // tx port, tx alternate, tx pin
	.rx_port        = GPIOA, 
    .rx_af          = GPIO_AF_7, 
    .rx_pin         = GPIO_PIN_10,                           // rx port, rx alternate, rx pin
},
#endif

#ifdef BSP_USING_UART1
{
    .name           = LCD_UART_NAME,
	.usart_periph   = USART1,                                 // uart peripheral index
	.irq            = USART1_IRQn,                            // uart iqrn
	.per_clk        = RCU_USART1,
    .dma_clk        = RCU_DMA0,
    .dma_periph     = DMA0,
    .dma_tx_channel = DMA_CH6,
    .dma_rx_channel = DMA_CH5,
    .dev_flag       = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_DMA_TX | RT_DEVICE_FLAG_INT_RX,    
    .tx_gpio_clk    = RCU_GPIOD, 
    .rx_gpio_clk    = RCU_GPIOD,                              // periph clock, tx gpio clock, rt gpio clock
	.tx_port        = GPIOD, 
    .tx_af          = GPIO_AF_7, 
    .tx_pin         = GPIO_PIN_5,                            // tx port, tx alternate, tx pin
	.rx_port        = GPIOD, 
    .rx_af          = GPIO_AF_7, 
    .rx_pin         = GPIO_PIN_6,                           // rx port, rx alternate, rx pin  
},
#endif

#ifdef BSP_USING_UART2
{
    .name           = RS485_UART_NAME,
	.usart_periph   = USART2,                                 // uart peripheral index
	.irq            = USART2_IRQn,                            // uart iqrn
	.per_clk        = RCU_USART2, 
    .dev_flag       = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
    .tx_gpio_clk    = RCU_GPIOD, 
    .rx_gpio_clk    = RCU_GPIOD,                              // periph clock, tx gpio clock, rt gpio clock
	.tx_port        = GPIOD, 
    .tx_af          = GPIO_AF_7, 
    .tx_pin         = GPIO_PIN_8,                            // tx port, tx alternate, tx pin
	.rx_port        = GPIOD, 
    .rx_af          = GPIO_AF_7, 
    .rx_pin         = GPIO_PIN_9,                           // rx port, rx alternate, rx pin
},
#endif

#ifdef BSP_USING_UART3
{    
#if defined(A5158_EDITION)
    .name           = PCIE_UART_NAME,
#else
	.name           = PCIE_UART_NAME,
#endif
	.usart_periph   = UART3,                                 // uart peripheral index
	.irq            = UART3_IRQn,                            // uart iqrn
	.per_clk        = RCU_UART3, 
    .dma_clk        = RCU_DMA0,
    .dma_periph     = DMA0,
    .dma_tx_channel = DMA_CH4,
    .dma_rx_channel = DMA_CH2,
    .dev_flag       = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
    .tx_gpio_clk    = RCU_GPIOC, 
    .rx_gpio_clk    = RCU_GPIOC,                              // periph clock, tx gpio clock, rt gpio clock
	.tx_port        = GPIOC, 
    .tx_af          = GPIO_AF_8, 
    .tx_pin         = GPIO_PIN_10,                            // tx port, tx alternate, tx pin
	.rx_port        = GPIOC, 
    .rx_af          = GPIO_AF_8, 
    .rx_pin         = GPIO_PIN_11,                           // rx port, rx alternate, rx pin   
},
#endif

#ifdef BSP_USING_UART4
{
    .name           = METER_UART_NAME,
	.usart_periph   = UART4,                                 // uart peripheral index
	.irq            = UART4_IRQn,                            // uart iqrn
	.per_clk        = RCU_UART4, 
    .dma_clk        = RCU_DMA0,
    .dma_periph     = DMA0,
    .dma_tx_channel = DMA_CH7,
    .dma_rx_channel = DMA_CH0,
    .dev_flag       = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
    .tx_gpio_clk    = RCU_GPIOC, 
    .rx_gpio_clk    = RCU_GPIOD,                              // periph clock, tx gpio clock, rt gpio clock
	.tx_port        = GPIOC, 
    .tx_af          = GPIO_AF_8, 
    .tx_pin         = GPIO_PIN_12,                            // tx port, tx alternate, tx pin
	.rx_port        = GPIOD, 
    .rx_af          = GPIO_AF_8, 
    .rx_pin         = GPIO_PIN_2,                           // rx port, rx alternate, rx pin  
},
#endif

#ifdef BSP_USING_UART5
{
    .name           = ISO_15118_UART_NAME,
	.usart_periph   = USART5,                                 // uart peripheral index
	.irq            = USART5_IRQn,                            // uart iqrn
	.per_clk        = RCU_USART5, 
    .dev_flag       = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
    .tx_gpio_clk    = RCU_GPIOC, 
    .rx_gpio_clk    = RCU_GPIOC,                              // periph clock, tx gpio clock, rt gpio clock
	.tx_port        = GPIOC, 
    .tx_af          = GPIO_AF_8, 
    .tx_pin         = GPIO_PIN_6,                            // tx port, tx alternate, tx pin
	.rx_port        = GPIOC, 
    .rx_af          = GPIO_AF_8, 
    .rx_pin         = GPIO_PIN_7,                           // rx port, rx alternate, rx pin 
},
#endif

#ifdef BSP_USING_UART6
{
    .name           = NFC_UART_NAME,
	.usart_periph   = UART6,                                 // uart peripheral index
	.irq            = UART6_IRQn,                            // uart iqrn
	.per_clk        = RCU_UART6, 
    .dma_clk        = RCU_DMA0,
    .dma_periph     = DMA0,
    .dma_tx_channel = DMA_CH1,
    .dma_rx_channel = DMA_CH3,
    .dev_flag       = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
    .tx_gpio_clk    = RCU_GPIOF, 
    .rx_gpio_clk    = RCU_GPIOF,                              // periph clock, tx gpio clock, rt gpio clock
	.tx_port        = GPIOF, 
    .tx_af          = GPIO_AF_8, 
    .tx_pin         = GPIO_PIN_7,                            // tx port, tx alternate, tx pin
	.rx_port        = GPIOF, 
    .rx_af          = GPIO_AF_8, 
    .rx_pin         = GPIO_PIN_6,                           // rx port, rx alternate, rx pin   
},
#endif

#ifdef BSP_USING_UART7
{
    .name           = WIFI_UART_NAME,
	.usart_periph   = UART7,                                 // uart peripheral index
	.irq            = UART7_IRQn,                            // uart iqrn
	.per_clk        = RCU_UART7, 
    .dev_flag       = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
    .tx_gpio_clk    = RCU_GPIOE, 
    .rx_gpio_clk    = RCU_GPIOE,                              // periph clock, tx gpio clock, rt gpio clock
	.tx_port        = GPIOE, 
    .tx_af          = GPIO_AF_8, 
    .tx_pin         = GPIO_PIN_0,                            // tx port, tx alternate, tx pin
	.rx_port        = GPIOE, 
    .rx_af          = GPIO_AF_8, 
    .rx_pin         = GPIO_PIN_1,                           // rx port, rx alternate, rx pin 
#if defined(AT_DEVICE_USING_W15)
	.rts_pin        = GET_PIN(C, 2),      
	.cts_pin        = GET_PIN(F, 10),       
#endif
},
#endif
    
};

static drv_uart_t uart_obj[sizeof(uart_config_array) / sizeof(uart_config_array[0])] = {0};

/**
* @brief UART MSP Initialization
*        This function configures the hardware resources used in this example:
*           - Peripheral's clock enable
*           - Peripheral's GPIO Configuration
*           - NVIC configuration for UART interrupt request enable
* @param huart: UART handle pointer
* @retval None
*/
static void gd32_uart_gpio_init(uart_config_param *uart)
{
	/* enable USART clock */
	rcu_periph_clock_enable(uart->tx_gpio_clk);
	rcu_periph_clock_enable(uart->rx_gpio_clk);
	rcu_periph_clock_enable(uart->per_clk);
    
	/* connect port to USARTx_Tx */
	gpio_af_set(uart->tx_port, uart->tx_af, uart->tx_pin);

	/* connect port to USARTx_Rx */
	gpio_af_set(uart->rx_port, uart->rx_af, uart->rx_pin);

	/* configure USART Tx as alternate function push-pull */
	gpio_mode_set(uart->tx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, uart->tx_pin);
	gpio_output_options_set(uart->tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, uart->tx_pin);

	/* configure USART Rx as alternate function push-pull */
	gpio_mode_set(uart->rx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, uart->rx_pin);
	gpio_output_options_set(uart->rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, uart->rx_pin);
}

static void gd32_uart_dma_init(struct rt_serial_device *serial)
{   
    dma_single_data_parameter_struct dma_init_struct = {0};
    drv_uart_t * uart = rt_container_of(serial, drv_uart_t, serial);
    
    /* enable DMA */
    rcu_periph_clock_enable(uart->uart_config->dma_clk);
    
    if (serial->parent.flag & RT_DEVICE_FLAG_DMA_TX){
        dma_deinit(uart->uart_config->dma_periph, uart->uart_config->dma_tx_channel);
        dma_init_struct.direction           = DMA_MEMORY_TO_PERIPH;
        dma_init_struct.memory0_addr        = 0;
        dma_init_struct.memory_inc          = DMA_MEMORY_INCREASE_ENABLE;
        dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
        dma_init_struct.number              = 0;
        dma_init_struct.periph_addr         = (uint32_t)&USART_DATA(uart->uart_config->usart_periph);
        dma_init_struct.periph_inc          = DMA_PERIPH_INCREASE_DISABLE;
        dma_init_struct.priority            = DMA_PRIORITY_ULTRA_HIGH;
        dma_single_data_mode_init(uart->uart_config->dma_periph, uart->uart_config->dma_tx_channel, &dma_init_struct);
        /* configure DMA mode */
        dma_circulation_disable(uart->uart_config->dma_periph, uart->uart_config->dma_tx_channel);
        dma_channel_subperipheral_select(uart->uart_config->dma_periph, uart->uart_config->dma_tx_channel, DMA_SUBPERI4);
    }

    if (serial->parent.flag & RT_DEVICE_FLAG_DMA_RX){
        dma_deinit(uart->uart_config->dma_periph, uart->uart_config->dma_rx_channel);
        dma_init_struct.direction           = DMA_PERIPH_TO_MEMORY;
        dma_init_struct.memory0_addr        = 0;
        dma_init_struct.memory_inc          = DMA_MEMORY_INCREASE_ENABLE;
        dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
        dma_init_struct.number              = 0;
        dma_init_struct.periph_addr         = (uint32_t)&USART_DATA(uart->uart_config->usart_periph);
        dma_init_struct.periph_inc          = DMA_PERIPH_INCREASE_DISABLE;
        dma_init_struct.priority            = DMA_PRIORITY_ULTRA_HIGH;
        dma_single_data_mode_init(uart->uart_config->dma_periph, uart->uart_config->dma_rx_channel, &dma_init_struct);
        /* configure DMA mode */
        dma_circulation_disable(uart->uart_config->dma_periph, uart->uart_config->dma_rx_channel);
        dma_channel_subperipheral_select(uart->uart_config->dma_periph, uart->uart_config->dma_rx_channel, DMA_SUBPERI4);
    }
}

static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
	RT_ASSERT(serial != RT_NULL);
	RT_ASSERT(cfg != RT_NULL);
	drv_uart_t * uart = rt_container_of(serial, drv_uart_t, serial);
	
	gd32_uart_gpio_init(uart->uart_config);
	
	usart_baudrate_set(uart->uart_config->usart_periph, cfg->baud_rate);

	switch(cfg->data_bits){
	case DATA_BITS_8:
		usart_word_length_set(uart->uart_config->usart_periph, USART_WL_8BIT);
	break;
	
	case DATA_BITS_9:
		usart_word_length_set(uart->uart_config->usart_periph, USART_WL_9BIT);
	break;
	
	default:
		usart_word_length_set(uart->uart_config->usart_periph, USART_WL_8BIT);
	break;
	}
	
	switch(cfg->stop_bits){
	case STOP_BITS_1:
		usart_stop_bit_set(uart->uart_config->usart_periph, USART_STB_1BIT);          ///<1bit停止位
	break;
	case STOP_BITS_2:
		usart_stop_bit_set(uart->uart_config->usart_periph, USART_STB_2BIT);     	 ///<2bit停止位
	break;
	default:
		usart_stop_bit_set(uart->uart_config->usart_periph, USART_STB_1BIT);         ///<1bit停止位
	break;
	}
	
	switch(cfg->parity){
	case PARITY_NONE:
		usart_parity_config(uart->uart_config->usart_periph, USART_PM_NONE);         ///<无校验
	break;
	case PARITY_ODD:
		usart_parity_config(uart->uart_config->usart_periph, USART_PM_ODD);        ///<奇检验
	break;
	case PARITY_EVEN:
		usart_parity_config(uart->uart_config->usart_periph, USART_PM_EVEN);         ///<偶检验
	break;
	default:
		usart_parity_config(uart->uart_config->usart_periph, USART_PM_NONE);         ///<无校验
	break;
	}	
    
    if ( !(serial->parent.flag & RT_DEVICE_FLAG_DMA_RX) ){
        NVIC_SetPriority(uart->uart_config->irq, 0);
        NVIC_EnableIRQ(uart->uart_config->irq);
    }
  
	usart_receive_config(uart->uart_config->usart_periph, USART_RECEIVE_ENABLE);
	usart_transmit_config(uart->uart_config->usart_periph, USART_TRANSMIT_ENABLE);
	usart_enable(uart->uart_config->usart_periph);
      
#ifdef RT_SERIAL_USING_DMA
    gd32_uart_dma_init(serial);
#endif
    
	return RT_EOK;
}

static rt_err_t uart_control(struct rt_serial_device *serial, int cmd,void *arg)
{
	drv_uart_t * uart;
	RT_ASSERT(serial != RT_NULL);
	uart = rt_container_of(serial, drv_uart_t, serial);
	switch (cmd){       
	case RT_DEVICE_CTRL_CLR_INT:																			/* disable interrupt */	
	    /* disable rx irq */
		NVIC_DisableIRQ(uart->uart_config->irq);
		/* disable interrupt */
		usart_interrupt_disable(uart->uart_config->usart_periph, USART_INT_RBNE);
	break;

	case RT_DEVICE_CTRL_SET_INT:																			/* enable interrupt */
		NVIC_SetPriority(uart->uart_config->irq, 0);
		/* enable rx irq */
		NVIC_EnableIRQ(uart->uart_config->irq);
		/* enable interrupt */
		usart_interrupt_enable(uart->uart_config->usart_periph, USART_INT_RBNE);
	break;  

	case RT_DEVICE_CTRL_CLOSE:																				/* 去初始化串口 */
		usart_deinit(uart->uart_config->usart_periph);
	break;
	}
	return RT_EOK;
}

static int uart_putc(struct rt_serial_device *serial, char ch)
{
	drv_uart_t * uart;
	rt_tick_t start_tick;
	RT_ASSERT(serial != RT_NULL);
	uart = rt_container_of(serial, drv_uart_t, serial);
	/* 轮询发送 */
	usart_data_transmit(uart->uart_config->usart_periph, ch);
	start_tick = rt_tick_get();
	while((usart_flag_get(uart->uart_config->usart_periph, USART_FLAG_TC) == RESET)){
		if (rt_tick_get() - start_tick >= 10){
			return -1;
		}
	}
	
	return 1;
}

static int uart_getc(struct rt_serial_device *serial)
{
	int ch = -1;
	drv_uart_t * uart;
	
	RT_ASSERT(serial != RT_NULL);
	uart = rt_container_of(serial, drv_uart_t, serial);

	if ( usart_flag_get(uart->uart_config->usart_periph, USART_FLAG_RBNE) != RESET ){
		 ch = usart_data_receive(uart->uart_config->usart_periph);
	}
	return ch;
}

static rt_size_t usart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
{
    drv_uart_t * uart;
	uint32_t dma_channel;
    
    rt_tick_t start_tick;
    
	RT_ASSERT(serial != RT_NULL);

	uart = rt_container_of(serial, drv_uart_t, serial);
    
    switch (direction)
    {
    case RT_SERIAL_DMA_TX:
        dma_channel = uart->uart_config->dma_tx_channel;
        usart_dma_transmit_config(uart->uart_config->usart_periph, USART_DENT_ENABLE);
    break;
        
    case RT_SERIAL_DMA_RX:    
        dma_channel = uart->uart_config->dma_rx_channel;
        usart_dma_receive_config(uart->uart_config->usart_periph, USART_DENR_ENABLE);  
    break;
        
    default:
    return 0; 
    }   

    dma_transfer_number_config(uart->uart_config->dma_periph, dma_channel, size);
    dma_memory_address_config(uart->uart_config->dma_periph, dma_channel, DMA_MEMORY_0, (uint32_t)buf);
    
    dma_channel_enable(uart->uart_config->dma_periph, dma_channel);
    /* wait until USART DMA channel transfer complete */
    start_tick = rt_tick_get();
    while (RESET == dma_flag_get(uart->uart_config->dma_periph, dma_channel, DMA_INTF_FTFIF)){
        if (rt_tick_get() - start_tick >= 20){
			return 0;
		}
    }   
    dma_channel_disable(uart->uart_config->dma_periph, dma_channel);
        
	return size;
}

static const struct rt_uart_ops uart_ops =
{
	.configure      = uart_configure,
	.control        = uart_control,
	.putc           = uart_putc,
	.getc           = uart_getc,
    .dma_transmit   = usart_dma_transmit
};

static void uart_isr(struct rt_serial_device *serial) 
{ 
	RT_ASSERT(serial != RT_NULL);
	drv_uart_t *uart = rt_container_of(serial, drv_uart_t, serial);
	/* UART in mode Receiver -------------------------------------------------*/
	if ((usart_interrupt_flag_get(uart->uart_config->usart_periph, USART_INT_FLAG_RBNE) != RESET) &&
		(usart_flag_get(uart->uart_config->usart_periph, USART_FLAG_RBNE) != RESET)) {		
		rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
		/* Clear RXNE interrupt flag */
		usart_flag_clear(uart->uart_config->usart_periph, USART_FLAG_RBNE);
	}	
}

#if defined(BSP_USING_UART0)
void USART0_IRQHandler(void)
{
	/* enter interrupt */
	rt_interrupt_enter();

	uart_isr(&(uart_obj[uart0].serial)); 

	/* leave interrupt */
	rt_interrupt_leave();
}
#endif /* BSP_USING_UART0 */

#if defined(BSP_USING_UART1)
void USART1_IRQHandler(void)
{
	/* enter interrupt */
	rt_interrupt_enter();

	uart_isr(&(uart_obj[uart1].serial)); 

	/* leave interrupt */
	rt_interrupt_leave();
}
#endif /* BSP_USING_UART1 */

#if defined(BSP_USING_UART2)
void USART2_IRQHandler(void)
{
	/* enter interrupt */
	rt_interrupt_enter();

	uart_isr(&(uart_obj[uart2].serial)); 

	/* leave interrupt */
	rt_interrupt_leave();
}
#endif /* BSP_USING_UART2 */

#if defined(BSP_USING_UART3)
void UART3_IRQHandler(void)
{
	/* enter interrupt */
	rt_interrupt_enter();

	uart_isr(&(uart_obj[uart3].serial)); 

	/* leave interrupt */
	rt_interrupt_leave();
}
#endif /* BSP_USING_UART3 */

#if defined(BSP_USING_UART4)
void UART4_IRQHandler(void)
{
	/* enter interrupt */
	rt_interrupt_enter();

	uart_isr(&(uart_obj[uart4].serial)); 

	/* leave interrupt */
	rt_interrupt_leave();
}
#endif /* BSP_USING_UART4 */

#if defined(BSP_USING_UART5)
void USART5_IRQHandler(void)
{
	/* enter interrupt */
	rt_interrupt_enter();

	uart_isr(&(uart_obj[uart5].serial)); 

	/* leave interrupt */
	rt_interrupt_leave();
}
#endif /* BSP_USING_UART5 */

#if defined(BSP_USING_UART6)
void UART6_IRQHandler(void)
{
	/* enter interrupt */
	rt_interrupt_enter();

	uart_isr(&(uart_obj[uart6].serial)); 

	/* leave interrupt */
	rt_interrupt_leave();
}
#endif /* BSP_USING_UART6 */

#if defined(BSP_USING_UART7)
struct rt_serial_device serial7;

void UART7_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    uart_isr(&(uart_obj[uart7].serial)); 

    /* leave interrupt */
    rt_interrupt_leave();
}

#endif /* BSP_USING_UART7 */

int hw_uart_init(void)
{   
	rt_size_t obj_num = sizeof(uart_obj) / sizeof(drv_uart_t);
	struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
	rt_err_t result = 0;
	
	for (uint8_t i = 0; i < obj_num; i++)
	{
		/* init UART object */
		uart_obj[i].uart_config 	= &uart_config_array[i];
		uart_obj[i].serial.ops    	= &uart_ops;
		uart_obj[i].serial.config 	= config;

		/* register UART device */
		result = rt_hw_serial_register(&uart_obj[i].serial, 
										uart_obj[i].uart_config->name,
                                        uart_obj[i].uart_config->dev_flag, 
										NULL);
		RT_ASSERT(result == RT_EOK);
	}

  return result;
}

void finsh_uart_reconfig(void)
{
	struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
	rt_device_control(rt_console_get_device(), RT_DEVICE_CTRL_CONFIG, &config);
}

void finsh_uart_clear(void)
{
	rt_device_control(rt_console_get_device(), RT_DEVICE_CTRL_CLR_INT, RT_NULL);
}
#endif

